home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * File Name : XLATE.C
- * Description : Text Substitution Software tool for Multi Language
- * Support.
- * Author : R. Scott Guthrie / All Rights Reserved
- * History : 01/13/94 - Modification to add Speed-Up code for
- * loading '.TRB' files.
- * 01/20/94 - Function names changed to avoid possible
- * conflicts with users code.
- **************************************************************************/
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * Function : XlateSet()
- * Arguments : (char *) File name of translation file (without ext).
- * Return : None
- * Description : USER CALLABLE - This function sets the file name
- * to be used for string translation.
- * If user does not call this function, the translate
- * system will use the default file specified in
- * constant 'DefaultFileName'. No checking for
- * file existance is performed by this function.
- * ---------------
- * Function : Xlate()
- * Arguments : (char *) String to be translated.
- * Return : (char *) Translation string.
- * Description : USER CALLABLE - This function translates the string
- * passed in, to the translated version in the translate
- * table. If the table has not been loaded, it
- * initiates that action before attempting the
- * translation. If no match is found, then a '?' is
- * returned.
- * ---------------
- * Function : XlateLoad()
- * Arguments : (char *) File name of translation file.
- * Return : (int) function status
- * Description : INTERNAL FUNCTION - Called by 'Xlate()' to build the
- * translation table.
- * ---------------
- * Function : XlateLoadBinary()
- * Arguments : (FILE) File Descriptor of the binary translation file.
- * Return : (int) function status
- * Description : INTERNAL FUNCTION - Called by 'XlateLoad()' to
- * load the binary translation table from a TRB file.
- * ---------------
- * Function : XlateLoadText()
- * Arguments : (FILE) File descriptor of the Text translation file.
- * Return : (int) function status
- * Description : INTERNAL FUNCTION - Called by 'XlateLoad()' to
- * build and load the translation table from a TRN file.
- * ---------------
- * Function : XlateFree()
- * Arguments : None
- * Return : None
- * Description : USER CALLABLE - This function is used to free the
- * memory allocated for the TRANSLATE system. It is used
- * internally and callable directly.
- * ---------------
- * Function : XlateSearchCompare()
- * Arguments : (const void *) Pointer to compare string 1.
- * (const void *) Pointer to compare string 2.
- * Return : (int) Compare status
- * Description : INTERNAL FUNCTION - Search Compare Function.
- * ---------------
- * Function : XlateSortCompare()
- * Arguments : (const void *) Pointer to compare string 1.
- * (const void *) Pointer to compare string 2.
- * Return : (int) Compare status
- * Description : INTERNAL FUNCTION - Sort Compare Function.
- * ---------------
- * Function : XlateGetString()
- * Arguments : (FILE) File descriptor of the Text translation file.
- * (char *) Pointer to a string.
- * Return : (int) Number of characters in string or -1 for EOF
- * Description : INTERNAL FUNCTION - Called by 'XlateLoadText()'
- * Reads and parses through the TRN file and returns
- * the next String value found.
- * ---------------
- * Function : XlateCreateTable()
- * Arguments : (int) Number of XLATE entries.
- * Return : (int) 1 for success, -1 for Allocation Error.
- * Description : INTERNAL FUNCTION - Called by 'XlateLoadText()'
- * and 'XlateLoadBinary()' to allocate memory
- * for the Translate Table.
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <io.h>
- #include <fcntl.h>
- #include <alloc.h>
- #include <assert.h>
- #include "xlate.h"
-
- /* GLOBAL VARAIBLES */
- XLATE *XlateBase = NULL;
- int XlateLines = 0;
- char *XlateFile = XlateDefaultFileName;
-
- /* FUNCTION DEFINITIONS */
- /*========================================*/
- void XlateSet(char *translate_file_name)
- /*========================================*/
- /* Establish Translation Table Name */
- {
- XlateFree(); /* clear any existing table */
- XlateFile = translate_file_name; /* set to new file name. */
- return;
- } /* end function 'XlateSet()' */
-
- /*=============================*/
- char *Xlate(char *key_string)
- /*=============================*/
- /* Translate a given KEY string to a Translated version by searching */
- /* through the Translation table. */
- {
- XLATE *node; /* Allocate pointer to an XLATE node */
- static char Default[] = "?"; /* Default String */
-
- /* If the translation file has not been read in, then load it. */
- if(!XlateBase)
- (void) XlateLoad(XlateFile);
-
- if(!XlateBase) /* If file wasn't loaded (found), */
- return(Default); /* Return the default string */
-
- /* Search translation block for matching key string. */
- if((node = (XLATE *)bsearch(key_string, XlateBase,
- XlateLines, sizeof(XLATE), XlateSearchCompare)) == NULL)
- return(Default); /* If no KEY is found */
-
- /* Return pointer to the translated value. */
- return(node->translated_value);
-
- } /* end function 'Xlate()' */
-
- /*=============================*/
- int XlateLoad(char *filename)
- /*=============================*/
- /* This function is used to load a translation definition file. */
- /* Returns the number of Translate Table Entires or: */
- /* 0 if no file is found. (either ".TRB" or ".TRN") */
- /* -1 if memory allocation error encountered. */
- {
- char filenamebuf[128]; /* Filename Buffer */
- FILE *fd; /* Translation File Descriptor */
- int retval = 0; /* return variable */
-
- /* Delete any existing 'in memory' translate table */
- XlateFree();
-
- /* Attempt to open a Binary Version of the translate file. */
- sprintf(filenamebuf, "%s.TRB", filename);
- if((fd = fopen(filenamebuf, "rb")) != NULL)
- {
- retval = XlateLoadBinary(fd);
- fclose(fd); /* Finished with file */
- }
- else /* Binary file did not open */
- {
- /* Attempt to open a Text Version of the translate file. */
- sprintf(filenamebuf, "%s.TRN", filename);
- if((fd = fopen(filenamebuf, "r")) != NULL)
- {
- retval = XlateLoadText(fd);
- fclose(fd); /* Finished with file */
- }
- }
- /* If there was an error, then free any memory that did happen */
- /* to get allocated for the table and any Keys or Results. */
- if(retval <= 0)
- XlateFree();
-
- return(retval);
- } /* end 'XlateLoad()' */
-
- /*=============================*/
- int XlateLoadBinary(FILE *fd)
- /*=============================*/
- /* Loads the binary version of the translate file. This loads */
- /* faster than the Text version. */
- {
- /* Binary File format is: */
- /* 4 bytes = ".TRB" (File Signature) */
- /* integer # of lines */
- /* integer # of line sets of: */
- /* integer size of key string */
- /* null terminated key string */
- /* integer size of result string */
- /* null terminated result string */
- /* (Note: The file is pre-sorted by Key Strings) */
-
- char signature[5]; /* buffer for signature string */
- int i; /* Loop Variable */
- int length; /* string length read from file */
- XLATE *node; /* Allocated Node */
-
- /* Get the file Signature */
- if(fread(signature, 4 * sizeof(char), 1, fd) != 1)
- return 0; /* Bad read from File */
- signature[4] = '\0'; /* terminating NULL for signature string */
- if(strcmp(signature, ".TRB") != 0)
- return 0; /* Not a ".TRB" Binary Translate File */
-
- /* Get the number of entries */
- if(fread(&XlateLines, sizeof(XlateLines), 1, fd) != 1)
- return 0; /* File Error - No Size Found. */
-
- /* Allocate the translate table memory */
- if(XlateCreateTable(XlateLines) == -1)
- return (-1); /* Allocation Error */
-
- node = XlateBase; /* point node to the table */
-
- for(i=0; i< XlateLines; i++)
- {
- /* PROCESS KEY VALUE */
- /* Get Length of Key Value */
- if(fread(&length, sizeof(length),1,fd) != 1)
- return(0); /* File Error - No Length Found. */
-
- /* Allocate Key String space */
- if((node->translate_key = (char*)malloc(sizeof(char) * length)) == NULL)
- return(-1); /* File Error - Allocation Failed */
-
- /* Read Key String into translate table */
-
- if(fread(node->translate_key, length, 1, fd) != 1)
- return(0); /* File Error - String not read correctly */
-
- /* PROCESS RESULT VALUE */
- /* Get Length of Result Value */
- if(fread(&length, sizeof(length),1,fd) != 1)
- return(0); /* File Error - No Length Found. */
-
- /* Allocate Result String space */
- if((node->translated_value = (char*)malloc(sizeof(char) * length)) == NULL)
- return(-1); /* File Error - Allocation Failed */
-
- /* Read Result String into translate table */
- if(fread(node->translated_value, length, 1, fd) != 1)
- return(0); /* File Error - String not read correctly */
-
- node++; /* Bump Node Pointer */
- }
- return(XlateLines);
- } /* end 'XlateLoadBinary()' */
-
- /*=======================================*/
- int XlateGetString(FILE *fd, char *str)
- /*=======================================*/
- /* Parser State Machine's Operation and Rules */
- /* */
- /* - Text Delimeters are square brackets. '[' and ']' */
- /* - 'Strings' are text values within delimeters. */
- /* - Whitespace is ignored except within Strings. */
- /* - Key and Result values are Strings. */
- /* - Any non-string text is ignored. (Considered a comment) */
- /* - Delimeters can be escaped with backslash '\' character. */
- /* - Backslash can be escaped with Blackslash. '\\' */
- /* - Key and Result values are interpreted as a Pair of Strings. */
- /* ( [Key value] followed by [Result value] ) */
- /* - The Key value and the Result value need not be on the same line, */
- /* but must be contigious. */
- /* - String values can be split across multiple lines, but newline */
- /* characters are NOT preserved. */
- /* - String lengths will be truncated to 'XlateMaxLength' characters. */
- /* */
- /* Returns: Length of string returned, or -1 for EOF */
- {
- /* Define State Types */
- enum {WhiteSpace, String, WhiteSpaceEscape,
- Escape, Truncate, TruncateEscape};
-
- int count; /* # of characters copied to str */
- int state = WhiteSpace; /* Current State of Parser */
- char *pos; /* Current position in str */
- char ch; /* Character being processed */
-
- count = 0;
- while((ch = (char) fgetc(fd)) != (char)EOF)
- {
- /* Test for full buffer */
- if(count == XlateMaxLength - 1) /* If the buffer is full, */
- state = Truncate; /* change state to Truncate. */
-
- switch(state)
- {
- case WhiteSpace: /* PROCESS WHITE SPACE */
- switch(ch) /* switch on char received */
- {
- case XlateOpenDelimeter:
- pos = str; /* Position to beginning of str */
- count = 0; /* zero the count value */
- state = String; /* Change state */
- break;
- case XlateEscapeCharacter: /* Escape Character encountered */
- state = WhiteSpaceEscape;
- break;
- default: /* ignore all other characters */
- break;
- }
- break;
-
- case String: /* PROCESS STRING VALUE */
- switch(ch) /* switch on char received */
- {
- case XlateCloseDelimeter: /* Close Delimeter encountered */
- *pos = '\0'; /* terminate buffer */
- return count; /* return string length */
- case XlateEscapeCharacter: /* Escape Character encountered */
- state = Escape; /* Change state */
- break;
- case '\n': /* Ignore newline character */
- break;
- default: /* Other character encountered */
- *pos++ = ch; /* Copy char to the buffer */
- count++; /* Bump character count */
- break;
- }
- break;
-
- case WhiteSpaceEscape: /* Ignore character found */
- state = WhiteSpace; /* after an escape while */
- break; /* scanning WhiteSpace. */
-
- case Escape: /* PROCESS ESCAPE */
- *pos++ = ch; /* Copy whatever it is... */
- count++; /* bump character count */
- state = String; /* reset to String State */
- break;
-
- case Truncate: /* Don't Copy Characters */
- switch(ch) /* switch on char received */
- {
- case XlateCloseDelimeter: /* Close Delimeter encountered */
- *pos = '\0'; /* terminate buffer */
- return count; /* return string length */
- case XlateEscapeCharacter: /* Escape Character encountered */
- state = TruncateEscape; /* Change state to process Escape */
- break;
- default: /* Other Character encountered */
- break; /* Do Nothing... */
- }
- break; /* Break Truncate Case */
-
- case TruncateEscape: /* Ignore character found */
- state = Truncate; /* after an escape while */
- break; /* Truncating. */
-
- default:
- assert(0); /* unreachable code */
- break;
-
- } /* end switch 'state' */
- } /* end while '!EOF' */
-
- *str = '\0'; /* Return NULL in str */
-
- return(-1); /* EOF reached */
- } /* end 'XlateGetString()' */
-
- /*===========================*/
- int XlateLoadText(FILE *fd)
- /*===========================*/
- /* This function is used to load a translation definition file. */
- /* Returns the number of lines processed or: */
- /* 0 if no such file, or */
- /* -1 Out of Memory or other memmory allocation error. */
- {
- char buffer[XlateMaxLength]; /* Text Buffer (data from file) */
- int i; /* Local Index Variable */
- XLATE *node; /* Translate Node */
- int length; /* Length of string */
-
- /* PASS 1 - Begin Processing */
- XlateLines = 0; /* Initialize string count. */
-
- /* Count number of String Values */
- while(XlateGetString(fd, buffer) >= 0) /* returns -1 at EOF */
- XlateLines++;
-
- /* XlateLines = number of strings found. (Half are Keys and Half */
- /* are Results) If there isn't an even number, then there won't be */
- /* a Result value for the last Key value. (or someone mis-counted) */
-
- if((XlateLines % 2) == 1) /* (Last Key value will be */
- XlateLines--; /* ignored since there is no */
- XlateLines /= 2; /* Result value for it.) */
-
- /* PASS 2 - Build in-memory table */
- /* Reset the translation file (to the top) */
- rewind(fd);
-
- /* Allocate the translate table memory */
- if(XlateCreateTable(XlateLines) == -1)
- return (-1); /* Allocation Error */
-
- /* Read the file entries into the Translate Table. */
- node = XlateBase; /* establish pointer to table */
- for(i = 0; i < XlateLines; i++) /* Loop for number of lines */
- {
- /* Get KEY value */
- length = XlateGetString(fd, buffer);
-
- /* Store KEY value in the table */
- if((node->translate_key = (char *)malloc(sizeof(char) *
- (length + 1))) == NULL)
- return(-1); /* Allocation Error */
- strcpy(node->translate_key, buffer); /* Move Value to Table */
-
- /* Get RESULT value */
- length = XlateGetString(fd, buffer);
-
- /* Store RESULT value in the table */
- if((node->translated_value = (char *)malloc(sizeof(char) *
- (length + 1))) == NULL)
- return(-1); /* Allocation Error */
- strcpy(node->translated_value, buffer);
-
- node++; /* Advance Table Pointer */
- } /* end 'for loop' */
-
- /* Sort the TRANSLATE Block. */
- qsort(XlateBase, XlateLines, sizeof(XLATE), XlateSortCompare);
-
- return(XlateLines); /* good return */
-
- } /* end function 'XlateLoadText' */
-
- /*=================================*/
- int XlateCreateTable(int entries)
- /*=================================*/
- {
- /* Allocate space for the file entries (XLATE structures) */
- if((XlateBase = (XLATE *) malloc(sizeof(XLATE) * entries)) == NULL)
- return (-1); /* return memory allocation error */
- memset(XlateBase, 0, (sizeof(XLATE) * entries)); /* zero table */
- return (1);
- }
-
- /*====================*/
- void XlateFree(void)
- /*====================*/
- /* Free allocated translate table (if any) */
- {
- XLATE *node; /* Translate Node Pointer */
- int i; /* local index variable */
-
- /* If allocated, Free the XLATE structure memory */
- if(XlateBase)
- {
- node = XlateBase; /* Establish node pointer */
- for(i = 0; i < XlateLines; i++) /* loop through table */
- {
- if(node->translate_key) /* Check for allocation */
- free(node->translate_key); /* Free key memory */
- if(node->translated_value) /* Check for allocation */
- free(node->translated_value); /* Free value memory */
- node++; /* Bump the Table pointer */
- }
-
- free(XlateBase); /* Free the Base memory */
- XlateBase = NULL; /* Reset base to NULL */
- }
- return;
- } /* end function 'XlateFree()' */
-
- /*====================================================*/
- int XlateSearchCompare(const void *a, const void *b)
- /*====================================================*/
- /* Compare function for searching the Translation Block. */
- {
- return(strcmp((char *) a, ((XLATE *) b)->translate_key));
-
- } /* end function 'XlateSearchCompare()' */
-
- /*==================================================*/
- int XlateSortCompare(const void *a, const void *b)
- /*==================================================*/
- /* Compare function for sorting the Translation Block. */
- {
- return(strcmp(((XLATE *) a)->translate_key,
- ((XLATE *) b)->translate_key));
-
- } /* end function 'XlateSortCompare()' */
-
- /* end source file 'xlate.c' */
-